﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.ServiceModel;

namespace ReadeAssetManager
{
    public partial class frmMain : Form
    {
        //private int childFormNumber = 0;
        private AMSServiceRef.User _usr;
        private FormWindowState _lastwindowstate;

        private enum _dlgopts { login, assets, reports, search, options, register };
        
        /// <summary>
        /// Contructor.
        /// Sets the window size and position based on the application settings and displays
        /// the log in control.
        /// </summary>
        public frmMain()
        {
            InitializeComponent();

            this.WindowState = Utility.MainWindowState;
            _lastwindowstate = this.WindowState;
            this.pnlNav.Size = Utility.MainSidebarSize;
            if (this.WindowState == FormWindowState.Normal)
            {
                this.Location = Utility.MainWindowPosition;
                this.Size = Utility.MainWindowSize;
            }
            LoadControl(_dlgopts.login);
        }

        private void mnuMainWindowTileCasc_Click(object sender, EventArgs e)
        {
            LayoutMdi(MdiLayout.Cascade);
        }

        private void mnuMainWindowTileVert_Click(object sender, EventArgs e)
        {
            LayoutMdi(MdiLayout.TileVertical);
        }

        private void mnuMainWindowTileHoriz_Click(object sender, EventArgs e)
        {
            LayoutMdi(MdiLayout.TileHorizontal);
        }

        private void mnuMainWindowCloseall_Click(object sender, EventArgs e)
        {
            foreach (Form childForm in MdiChildren)
            {
                childForm.Close();
            }
        }

        /// <summary>
        /// GetControlType
        /// Returns the type of the first control contained in the parent control.  Returns null if the Parent
        /// object has no children or does not possess a Controls property.
        /// </summary>
        /// <param name="Parent">[Control] The parent control that contains this control.</param>
        /// <returns>[Type] The type of the first control in the Parent.Controls list.</returns>
        private Type GetControlType(Control Parent)
        {
            try
            {
                if (Parent.Controls.Count > 0)
                {
                    return Parent.Controls[0].GetType();
                }
                else
                {
                    return null;
                }
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// LoadControl
        /// Loads the user-defined control as specified by the Options enumeration.
        /// </summary>
        /// <param name="Options">[_dlgopts] An enumeration indicating which application option the
        /// user wants to view.</param>
        private void LoadControl(_dlgopts Options)
        {
            switch (Options)
            {
                case _dlgopts.assets:
                    if (!(GetControlType(pnlItemOpts) == typeof(ucAssets)))
                    {
                        pnlItemOpts.Controls.Clear();
                        ucAssets assets = new ucAssets(_usr, LoadObjectForm);
                        pnlItemOpts.Controls.Add(assets);
                        assets.Dock = DockStyle.Fill;
                    }
                    break;
                case _dlgopts.login:
                    if (!(GetControlType(pnlItemOpts) == typeof(ucLogin)))
                    {
                        pnlItemOpts.Controls.Clear();
                        ucLogin login = new ucLogin(ProcessControlReturn, _usr);
                        pnlItemOpts.Controls.Add(login);
                        login.Dock = DockStyle.Fill;
                    }
                    break;
                case _dlgopts.options:
                    if (!(GetControlType(pnlItemOpts) == typeof(ucOptions)))
                    {
                        pnlItemOpts.Controls.Clear();
                        ucOptions options = new ucOptions();
                        pnlItemOpts.Controls.Add(options);
                        options.Dock = DockStyle.Fill;
                    }
                    break;
                case _dlgopts.reports:
                    if (!(GetControlType(pnlItemOpts) == typeof(ucReports)))
                    {
                        pnlItemOpts.Controls.Clear();
                        ucReports reports = new ucReports(_usr);
                        pnlItemOpts.Controls.Add(reports);
                        reports.Dock = DockStyle.Fill;
                    }
                    break;
                case _dlgopts.search:
                    if (!(GetControlType(pnlItemOpts) == typeof(ucSearch)))
                    {
                        pnlItemOpts.Controls.Clear();
                        ucSearch srch = new ucSearch(_usr, ShowSearchResults);
                        pnlItemOpts.Controls.Add(srch);
                        srch.Dock = DockStyle.Fill;
                    }
                    break;
                case _dlgopts.register:
                    if (!(GetControlType(pnlItemOpts) == typeof(ucRegister)))
                    {
                        pnlItemOpts.Controls.Clear();
                        ucRegister reg = new ucRegister(ProcessControlReturn);
                        pnlItemOpts.Controls.Add(reg);
                        reg.Dock = DockStyle.Fill;
                    }
                    break;
                default:
                    break;
            }
        }

        /// <summary>
        /// LoadObjectForm
        /// Method passed as a delegate to the ucAssets control.  This method loads the appropriate
        /// domain form as determined by the type of the ReturnedObject argument.
        /// </summary>
        /// <param name="ReturnedObject">[object] The domain object returned by the ucAssets control 
        /// that the user wants to view.</param>
        private void LoadObjectForm(object ReturnedObject)
        {
            if (ReturnedObject == null)
                return;

            if (ReturnedObject.GetType() == typeof(AMSServiceRef.Asset))
            {
                frmAsset frmA = new frmAsset((AMSServiceRef.Asset)ReturnedObject);
                frmA.MdiParent = this;
                frmA.Show();
            }
            else if (ReturnedObject.GetType() == typeof(AMSServiceRef.PurchaseData))
            {
                frmPurchase frmP = new frmPurchase((AMSServiceRef.PurchaseData)ReturnedObject);
                frmP.MdiParent = this;
                frmP.Show();
            }
            else if (ReturnedObject.GetType() == typeof(AMSServiceRef.WarrantyData))
            {
                frmWarranty frmW = new frmWarranty((AMSServiceRef.WarrantyData)ReturnedObject);
                frmW.MdiParent = this;
                frmW.Show();
            }
            else if (ReturnedObject.GetType() == typeof(AMSServiceRef.ScheduleData))
            {
                frmSchedule frmS = new frmSchedule((AMSServiceRef.ScheduleData)ReturnedObject);
                frmS.MdiParent = this;
                frmS.Show();
            }
            else if (ReturnedObject.GetType() == typeof(AMSServiceRef.ServiceData))
            {
                frmService frmS = new frmService((AMSServiceRef.ServiceData)ReturnedObject);
                frmS.MdiParent = this;
                frmS.Show();
            }
            else
            {
                /* Something unexpected happened.  Since the ucAssetsTree control responds to a
                 * doubleclick, this option could fire because no TreeNode was selected when the
                 * doubleclick event fired.  Displaying a popup error would be really annoying
                 * and probably unnecessary.  Ignore this request.
                 */
            }
        }

        /// <summary>
        /// ShowSearchResults
        /// Displays a frmAssetSearch userform containing the results from the asset search.
        /// </summary>
        /// <param name="ResultsList">[object] Contains the search results from the search control as a List.</param>
        private void ShowSearchResults(object ResultsList)
        {
            try
            {
                frmAssetSearch srch = new frmAssetSearch((List<AMSServiceRef.Asset>)ResultsList, LoadObjectForm);
                srch.MdiParent = this;
                srch.Show();
            }
            catch (Exception ex)
            {
                MessageBox.Show("The search results could not be displayed.\n\n" + ex.Message);
            }
        }

        /// <summary>
        /// mnuMainFileLogin
        /// Loads the login/logout control when the user clicks the Login option from the File menu.
        /// </summary>
        /// <param name="sender">[object] The mnuMainFileLogin control.</param>
        /// <param name="e">[EventArgs] The standard event arguments for a Click event.</param>
        private void mnuMainFileLogin_Click(object sender, EventArgs e)
        {
            LoadControl(_dlgopts.login);
        }

        private void obMain_Click(object sender, OutlookStyleControls.OutlookBar.ButtonClickEventArgs e)
        {
            int idx = obMain.Buttons.IndexOf(e.SelectedButton);
            switch (idx)
            {
                case 0:             // Assets was clicked.
                    LoadControl(_dlgopts.assets);
                    break;
                case 1:             // Reports was clicked.
                    LoadControl(_dlgopts.reports);
                    break;
                case 2:             // Search was clicked.
                    LoadControl(_dlgopts.search);
                    break;
                case 3:             // Options was clicked.
                    LoadControl(_dlgopts.options);
                    break;
                case 4:             // Log In/Out was clicked.
                    LoadControl(_dlgopts.login);
                    break;
                default:            // Something unexpected happened.
                    break;
            }
        }

        /// <summary>
        /// ProcessControlReturn
        /// Method passed as a delegate to a user-defined control.  This method returns the control
        /// that invoked it so that frmMain can respond.
        /// </summary>
        /// <param name="ctrl">The user control that called this delegate.</param>
        private void ProcessControlReturn(UserControl ctrl)
        {
            if (ctrl.GetType() == typeof(ucLogin))
            {
                _usr = ((ucLogin)ctrl).CurrentUser;
                if (_usr != null)
                {
                    sslStatus.Text = "Welcome " + _usr.Name + "!";
                    mnuMainFileLogin.Text = "Log Out";
                }
                else
                {
                    sslStatus.Text = "Logged out.";
                    mnuMainFileLogin.Text = "Log In";
                }
            }
            else if (ctrl.GetType() == typeof(ucRegister))
            {
                _usr = ((ucRegister)ctrl).CurrentUser;
                if (_usr != null)
                {
                    sslStatus.Text = "Registration sucessful " + _usr.Name + "!";
                }
                else
                    sslStatus.Text = "Registration failed.";
            }
            
        }

        /// <summary>
        /// RefreshAssetList
        /// If the ucAssets control is currently active, forces a reload of the list.  This method
        /// is called by the domain forms to cause the assets control to display updated records.
        /// </summary>
        /// <param name="CurrentUser">[AMSServiceRef.User] The current user of the application.</param>
        public void RefreshAssetList(AMSServiceRef.User CurrentUser)
        {
            _usr = CurrentUser;
            if ((GetControlType(pnlItemOpts) == typeof(ucAssets)))
            {
                pnlItemOpts.Controls.Clear();
                ucAssets assets = new ucAssets(_usr, LoadObjectForm);
                pnlItemOpts.Controls.Add(assets);
                assets.Dock = DockStyle.Fill;
            }
        }

        private void frmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            Utility.MainWindowState = this.WindowState;
            Utility.SaveSettings();
        }

        private void frmMain_Resize(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Normal)
                Utility.MainWindowSize = this.Size;

            if (_lastwindowstate != FormWindowState.Normal && this.WindowState == FormWindowState.Normal)
            {
                this.Size = Utility.MainWindowSize;
                this.Location = Utility.MainWindowPosition;
            }

            _lastwindowstate = this.WindowState;
        }

        private void frmMain_Move(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Normal)
                Utility.MainWindowPosition = this.Location;
        }

        private void frmMain_LocationChanged(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Normal)
                Utility.MainWindowPosition = this.Location;
        }

        private void pnlNav_Resize(object sender, EventArgs e)
        {
            Utility.MainSidebarSize = this.pnlNav.Size;
        }

        private void mnuMainAssetNew_Click(object sender, EventArgs e)
        {
            frmAsset frmA = new frmAsset(_usr);
            frmA.MdiParent = this;
            frmA.Show();
        }

        private void mnuMainHelpAbout_Click(object sender, EventArgs e)
        {
            MessageBox.Show("This is my CS400 final project that someday will allow me to rule the universe " +
                            "with an iron fist.\n\nOr at the very least help me stick it to the insurance " +
                            "company next time I get robbed.", "About");
        }

        /// <summary>
        /// mnuMainFileRegister
        /// Loads the registration control when the user clicks the Register option from the File menu.
        /// </summary>
        /// <param name="sender">[object] The mnuMainFileRegister control.</param>
        /// <param name="e">[EventArgs] The standard event arguments for a Click event.</param>
        private void mnuMainFileRegister_Click(object sender, EventArgs e)
        {
            LoadControl(_dlgopts.register);
        }

    }
}
